

import java.util.ArrayList;
import java.util.List;

/**
 *This parameterized class defines a Constraint Satisfaction Problem (CSP). 
 * 
 * @param <Type> refers to the type of values that the CSP variables will 
 * be assigned. Such a type will be specified at some later point either 
 * by subclassing or at runtime when instantiating 
 */
public abstract class CSPProblem<Type> {

	/**
	 * List<Variable<Type>> containing the CSP variables.
	 */
	private List<Variable<Type>> variables;
	
	/**
	 * Constructor method.
	 */
	public CSPProblem() {
		this.variables = new ArrayList<Variable<Type>>();
	}

	/**
	 * returns the CSP variables.
	 * 
	 * @return List<Variable<Type>> containing the CSP variables.
	 */
	public List<Variable<Type>> getVariables() {
		return this.variables;
	}

	
	/**
	 * Adds each variable from a list of variables to the CSP variable list.
	 * 
	 * @param variables List<Variable<Type>> containing the variables 
	 * that make the CSP variables.
	 */
	public void addVariables(List<Variable<Type>> variables) {
		if (variables != null) {
			for (Variable<Type> variable : variables) {
				this.addVariable(variable);
			}					
		}
	}
	
	/**
	 * Adds one new variable to the CSP variables.
	 * 
	 * @param variable Variable<Type> specifying the new variable to add.
	 */
	public void addVariable(Variable<Type> variable) {
		if (variable != null && !this.variables.contains(variable)) {
			this.variables.add(variable);
		}
	}
	
	/**
	 * Returns a string representation of the object. In general, the toString
	 * method returns a string that "textually represents" this object.
	 * 
	 * The result should be a concise but informative representation that is 
	 * easy for a person to read. It is recommended that all subclasses 
	 * override this method.
	 * 
	 * The toString method for class Object returns a string consisting of the
	 * name of the class of which the object is an instance, the at-sign 
	 * character `@', and the unsigned hexadecimal representation of the hash
	 * code of the object. 
	 * 
	 * In other words, this method returns a string equal to the value of: 
	 * getClass().getName() + '@' + Integer.toHexString(hashCode())
	 * 
	 * @return a string representation of the object.
	 */
	public String toString() {
		String result = " - Problem: '" + this.getClass().getSimpleName() + "'";
		
		for (Variable<Type> variable : variables) {
			result += "\n    * " + variable;
		}
		
		return result;
	}
}